package com.dlc.shop.platform.task;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import com.dlc.shop.bean.bo.ProductBO;
import com.dlc.shop.bean.enums.EsOperationType;
import com.dlc.shop.bean.event.EsProductUpdateEvent;
import com.dlc.shop.bean.model.Product;
import com.dlc.shop.bean.param.EsProductParam;
import com.dlc.shop.bean.vo.search.ProductSearchVO;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.dao.OrderMapper;
import com.dlc.shop.search.common.service.SearchProductService;
import com.dlc.shop.service.ProductService;
import com.dlc.shop.service.SkuStockService;
import com.dlc.shop.service.WarehouseService;
import lombok.RequiredArgsConstructor;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.stream.Collectors;


/**
 * @author yami
 */
@Component
@RequiredArgsConstructor
public class ProdTask {
    private final Logger logger = LoggerFactory.getLogger(getClass());
    private final OrderMapper orderMapper;
    private final ProductService productService;
    private final ApplicationContext applicationContext;
    private final SearchProductService searchProductService;
    private final ApplicationEventPublisher eventPublisher;
    private final SkuStockService skuStockService;
    private final WarehouseService warehouseService;


    @XxlJob("recoveryPreSaleProd")
    public void recoveryPreSaleProd(){
        logger.info("过了预售时间的商品，恢复成普通商品状态。。。");
        // 获取30分钟之前未支付的订单
        List<Product> products = productService.recoveryPreSaleProd();
        if(CollectionUtils.isEmpty(products)){
            return;
        }
        for (Product product : products) {
            //清除缓存
            productService.removeProdCacheByProdId(product.getProdId());
        }
    }

    @XxlJob("offlineExpireVirtualProd")
    public void offlineExpireVirtualProd(){
        logger.info("过了核销时间的虚拟商品，进行下架操作。");
        // 获取30分钟之前未支付的订单
        List<Product> products = productService.handleExpireVirtualProd();
        if(CollectionUtils.isEmpty(products)){
            return;
        }
        List<Long> ids = new ArrayList<>();
        for (Product product : products) {
            //清除缓存
            productService.removeProdCacheByProdId(product.getProdId());
            ids.add(product.getProdId());
        }
        applicationContext.publishEvent(new EsProductUpdateEvent(null, ids, EsOperationType.UPDATE_BATCH));
    }

    /**
     * 校验商品数量是否完整
     * 商品数据是否为最新的：根据商品更新时间判断
     */
    @XxlJob("verifyProdStockAndSold")
    public void verifySpuStockAndSold(){
        // 获取6分钟内提交订单中的商品列表
        List<Long> prodIds = orderMapper.listProdIdByTime(DateUtil.offsetDay(new Date(), -6));
        if (CollUtil.isEmpty(prodIds)) {
            return;
        }

        // 从es中查询商品的库存和销量数据
        EsProductParam productParam = new EsProductParam();
        productParam.setProdIds(prodIds);
        productParam.setFetchSource(new String[]{"prodId", "totalStocks", "soldNum", "actualSoldNum"});
        List<ProductSearchVO> esProdList = searchProductService.listSpuByProdIds(productParam);
        Map<Long, ProductSearchVO> prodMap = esProdList.stream().collect(Collectors.toMap(ProductSearchVO::getProdId, p -> p));


        // 从mysql中查询商品的库存和销量数据
        List<ProductBO> prodList = productService.listProdStockAndSold(prodIds);
        List<Long> updateList = new ArrayList<>();
        //比较es和mysql的商品数据
        for (ProductBO productBO : prodList) {
            ProductSearchVO productSearchVO = prodMap.get(productBO.getProdId());
            if (Objects.isNull(productSearchVO)) {
                continue;
            }
            boolean change = !Objects.equals(productBO.getTotalStocks(),  productSearchVO.getTotalStocks()) ||
                    !Objects.equals(productBO.getActualSoldNum() + productBO.getWaterSoldNum(), productSearchVO.getSoldNum()) ||
                    !Objects.equals(productBO.getActualSoldNum(), productSearchVO.getActualSoldNum());
            if (change) {
                updateList.add(productBO.getProdId());
            }
        }
        // 数据不一致的商品，更新es中的数据
        if (CollUtil.isNotEmpty(updateList)) {
            eventPublisher.publishEvent(new EsProductUpdateEvent(null, updateList, EsOperationType.UPDATE_SOLD_NUM_BATCH));
        }
    }


    @XxlJob("restoreStock")
    public void restoreStock() {
        try {
            // ===================== 恢复商品库存 =====================
            skuStockService.restoreStock();
        } catch (Exception e) {
            logger.error("恢复库存：", e);
            throw new YamiShopBindException(e.getMessage());
        }
    }


    @XxlJob("intiStock")
    public void intiStock() {
        try {
            // ===================== 初始化商品库存 =====================
            warehouseService.intiWarehouse();
            productService.intiStockPointSKu();
            String initStockStr = XxlJobHelper.getJobParam();
            Integer initStock = StrUtil.isNotBlank(initStockStr) ? Integer.parseInt(initStockStr) : 0;
            skuStockService.initStock(initStock);
            // ===================== 初始化商品库存记录 =====================
        } catch (Exception e) {
            throw new YamiShopBindException(e.getMessage());
        }
    }
}
